package com.kakarote.hrm.controller;

import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSONObject;
import com.kakarote.common.log.annotation.OperateLog;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.entity.OperationResult;
import com.kakarote.common.log.enums.ApplyEnum;
import com.kakarote.common.log.enums.BehaviorEnum;
import com.kakarote.common.log.enums.OperateObjectEnum;
import com.kakarote.common.log.enums.OperateTypeEnum;
import com.kakarote.core.common.Result;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.entity.UploadEntity;
import com.kakarote.core.exception.CrmException;
import com.kakarote.hrm.constant.RecruitPlanStatusEnum;
import com.kakarote.hrm.constant.RecruitReportLogConstant;
import com.kakarote.hrm.entity.BO.QueryRecruitPlanPageListBO;
import com.kakarote.hrm.entity.BO.SyncDataInformationBO;
import com.kakarote.hrm.entity.BO.UpdateRecruitPlanStatusBO;
import com.kakarote.hrm.entity.PO.HrmRecruitPlan;
import com.kakarote.hrm.entity.PO.HrmRecruitPosition;
import com.kakarote.hrm.entity.PO.HrmRecruitReportLog;
import com.kakarote.hrm.entity.VO.RecruitPlanVO;
import com.kakarote.hrm.service.IHrmRecruitPlanService;
import com.kakarote.hrm.service.IHrmRecruitPositionService;
import com.kakarote.hrm.service.IHrmRecruitReportLogService;
import com.kakarote.hrm.task.GzwEmployeeTask;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.kakarote.core.common.enums.SystemCodeEnum.SYSTEM_ERROR;

/**
 * <p>
 * 招聘计划表 前端控制器
 * </p>
 *
 * @author system
 * @since 2024-01-01
 */
@RestController
@RequestMapping("/hrmRecruitPlan")
@Api(tags = "招聘管理-招聘计划")
public class HrmRecruitPlanController {

    @Autowired
    private IHrmRecruitPlanService recruitPlanService;

    @Autowired
    private IHrmRecruitPositionService positionService;

    @Autowired
    private GzwEmployeeTask gzwEmployeeTask;

    @Autowired
    private IHrmRecruitReportLogService reportLogService;

    @ApiOperation("添加招聘计划")
    @PostMapping("/addRecruitPlan")
    @OperateLog(apply = ApplyEnum.HRM, object = OperateObjectEnum.HRM_RECRUIT_PLAN, behavior = BehaviorEnum.SAVE)
    public Result addRecruitPlan(@Validated @RequestBody HrmRecruitPlan recruitPlan) {
        OperationLog operationLog = recruitPlanService.addRecruitPlan(recruitPlan);
        return OperationResult.ok(operationLog);
    }

    @ApiOperation("修改招聘计划")
    @PostMapping("/setRecruitPlan")
    @OperateLog(apply = ApplyEnum.HRM, object = OperateObjectEnum.HRM_RECRUIT_PLAN, behavior = BehaviorEnum.UPDATE)
    public Result setRecruitPlan(@Validated @RequestBody HrmRecruitPlan recruitPlan) {
        OperationLog operationLog = recruitPlanService.setRecruitPlan(recruitPlan);
        return OperationResult.ok(operationLog);
    }

    @PostMapping("/downloadExcel")
    @ApiOperation("获取导入模板")
    public void downloadExcel(HttpServletResponse response) throws IOException {
        recruitPlanService.downloadExcel(response);
    }

    @PostMapping("/excelImport")
    @ApiOperation("excel导入计划")
    @OperateLog(apply = ApplyEnum.HRM, behavior = BehaviorEnum.EXCEL_IMPORT, type = OperateTypeEnum.IMPORT, object = OperateObjectEnum.HRM_RECRUIT_PLAN)
    public Result<JSONObject> excelImport(@RequestParam("file") MultipartFile file) {
        JSONObject object = recruitPlanService.excelImport(file);

        UploadEntity uploadEntity = recruitPlanService.uploadTempFile(file, null);

        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject("uploadData", uploadEntity.getFileId());
        operationLog.setOperationObject("name", "计划");

        JSONObject info = new JSONObject();
        info.put("count", object.getInteger("totalSize"));
        info.put("errorSize", object.getInteger("errSize"));
        info.put("errorFile", object.getString("token"));
        operationLog.setOperationInfo(info.toJSONString());
        return OperationResult.ok(object, ListUtil.toList(operationLog));
    }

    /**
     * 获取招聘计划详情
     *
     * @param planId 计划id
     */
    @ApiOperation("获取招聘计划详情")
    @PostMapping("/queryById/{planId}")
    public Result<RecruitPlanVO> queryById(@PathVariable("planId") Long planId) {
        RecruitPlanVO recruitPlanVO = recruitPlanService.queryById(planId);
        return Result.ok(recruitPlanVO);
    }

    @ApiOperation("查询招聘计划列表")
    @PostMapping("/queryRecruitPlanPageList")
    public Result<BasePage<RecruitPlanVO>> queryRecruitPlanPageList(@RequestBody QueryRecruitPlanPageListBO queryRecruitPlanPageListBO) {
        BasePage<RecruitPlanVO> page = recruitPlanService.queryRecruitPlanPageList(queryRecruitPlanPageListBO);
        return Result.ok(page);
    }

    @ApiOperation("修改招聘计划状态")
    @PostMapping("/updateRecruitPlanStatus")
    @OperateLog(apply = ApplyEnum.HRM, object = OperateObjectEnum.HRM_RECRUIT_PLAN)
    public Result updateRecruitPlanStatus(@RequestBody UpdateRecruitPlanStatusBO updateRecruitPlanStatusBO) {
        OperationLog operationLog = recruitPlanService.updateRecruitPlanStatus(updateRecruitPlanStatusBO);
        return OperationResult.ok(operationLog);
    }

    @PostMapping("/exportRecruitPlan")
    @ApiOperation("导出招聘计划")
    @OperateLog(apply = ApplyEnum.HRM, object = OperateObjectEnum.HRM_RECRUIT_PLAN, behavior = BehaviorEnum.EXCEL_EXPORT, type = OperateTypeEnum.EXPORT)
    public void exportRecruitPlan(@RequestBody QueryRecruitPlanPageListBO queryRecruitPlanPageListBO, HttpServletResponse response) throws IOException {
        recruitPlanService.exportRecruitPlan(response, queryRecruitPlanPageListBO);
    }

    @ApiOperation("根据ID删除招聘计划")
    @PostMapping("/deleteRecruitPlan/{planId}")
    @OperateLog(apply = ApplyEnum.HRM, object = OperateObjectEnum.HRM_RECRUIT_PLAN, behavior = BehaviorEnum.DELETE)
    public Result deleteRecruitPlanById(@PathVariable("planId") Long planId) {
        OperationLog operationLog = recruitPlanService.deleteRecruitPlanById(planId);
        return OperationResult.ok(operationLog);
    }

    /**
     * 计划审核回调
     */
    @PostMapping("/syncPlanCallback")
    public Result syncPlanCallback(@RequestBody SyncDataInformationBO syncDataInformationBO) {
        try {
            boolean b = recruitPlanService.syncPlanCallback(syncDataInformationBO);
            if (!b) {
                return Result.error(SYSTEM_ERROR.getCode(), "计划回调失败");
            }
            return Result.success();
        } catch (CrmException e) {
            return Result.error(SYSTEM_ERROR.getCode(), e.getMessage());
        } catch (Exception e) {
            return Result.error(SYSTEM_ERROR.getCode(), "计划回调失败");
        }
    }

    /**
     * 上报招聘计划
     * @param planId
     * @return
     */
    @ApiOperation("上报招聘计划")
    @PostMapping("/syncPlan/{planId}")
    public Result syncPlan(@PathVariable("planId") Long planId) {
        HrmRecruitPlan plan = recruitPlanService.getById(planId);
        if (plan == null) {
            return Result.error(SYSTEM_ERROR.getCode(), "计划不存在");
        }
        if (Objects.equals(plan.getStatus(), RecruitPlanStatusEnum.UNDER_REVIEW.getStatus())) {
            return Result.error(SYSTEM_ERROR.getCode(), "上报审核中，请勿重复上报");
        }

        //计划岗位
        List<HrmRecruitPosition> positionList = positionService.lambdaQuery().eq(HrmRecruitPosition::getPlanId, planId).list();
        if (positionList == null || positionList.isEmpty()){
            return Result.error(SYSTEM_ERROR.getCode(), "计划岗位不存在，请先新增计划岗位再上报");
        }
        
        // 执行同步上报
        boolean syncSuccess = gzwEmployeeTask.syncPlan(planId);
        if (!syncSuccess) {
            return Result.error(SYSTEM_ERROR.getCode(), "招聘计划上报失败");
        }
        
        // 更新计划状态为审核中
        boolean update = recruitPlanService.lambdaUpdate()
                .eq(HrmRecruitPlan::getPlanId, planId)
                .set(HrmRecruitPlan::getStatus, RecruitPlanStatusEnum.UNDER_REVIEW.getStatus())
                .update();
        if (!update) {
            return Result.error(SYSTEM_ERROR.getCode(), "计划状态更新失败");
        }

        //添加日志
        HrmRecruitReportLog hrmRecruitReportLog = new HrmRecruitReportLog();
        hrmRecruitReportLog.setPlanId(plan.getPlanId());
        hrmRecruitReportLog.setStatus(RecruitPlanStatusEnum.UNDER_REVIEW.getStatus());
        if (Objects.equals(RecruitPlanStatusEnum.PENDING_REPORT.getStatus(), plan.getStatus())) {
            hrmRecruitReportLog.setTitle(RecruitReportLogConstant.LogTitle.PLAN_REPORT.getName());
            hrmRecruitReportLog.setContent(RecruitReportLogConstant.LogContent.PLAN_REPORT.getName());
        } else if (Objects.equals(RecruitPlanStatusEnum.APPROVED.getStatus(), plan.getStatus())) {
            hrmRecruitReportLog.setTitle(RecruitReportLogConstant.LogTitle.PLAN_SECOND_REPORT.getName());
            hrmRecruitReportLog.setContent(RecruitReportLogConstant.LogContent.PLAN_SECOND_REPORT.getName());
        } else if (Objects.equals(RecruitPlanStatusEnum.REJECTED.getStatus(), plan.getStatus())) {
            hrmRecruitReportLog.setTitle(RecruitReportLogConstant.LogTitle.PLAN_AGAIN_REPORT.getName());
            hrmRecruitReportLog.setContent(RecruitReportLogConstant.LogContent.PLAN_AGAIN_REPORT.getName());
        }
        hrmRecruitReportLog.setCreateTime(LocalDateTime.now());
        reportLogService.save(hrmRecruitReportLog);
        
        return Result.ok();
    }

    /**
     * 上报招聘计划记录
     */
    @ApiOperation("上报招聘计划记录")
    @PostMapping("/syncPlanRecord")
    public Result syncPlanRecord() {
        boolean b = gzwEmployeeTask.syncPlanRecord();
        if (!b) {
            return Result.error(SYSTEM_ERROR.getCode(), "招聘记录上报失败");
        }
        return Result.ok();
    }

    /**
     * 上报启动岗位
     */
    @ApiOperation("上报启动岗位")
    @PostMapping("/syncStartPosition")
    public Result syncStartPosition() {
        boolean b = gzwEmployeeTask.syncStartPosition();
        if (!b) {
            return Result.error(SYSTEM_ERROR.getCode(), "启动岗位上报失败");
        }
        return Result.ok();
    }

    /**
     * 上报招聘过程
     */
    @ApiOperation("上报招聘过程")
    @PostMapping("/syncRecruitProces")
    public Result syncRecruitProces() {
        boolean b = gzwEmployeeTask.syncRecruitProces();
        if (!b) {
            return Result.error(SYSTEM_ERROR.getCode(), "招聘过程上报失败");
        }
        return Result.ok();
    }

    /**
     * 上报招聘人员
     */
    @ApiOperation("上报招聘人员")
    @PostMapping("/syncRecruitUser")
    public Result syncRecruitUser() {
        boolean b = gzwEmployeeTask.syncRecruitUser();
        if (!b) {
            return Result.error(SYSTEM_ERROR.getCode(), "招聘人员上报失败");
        }
        return Result.ok();
    }
}
